using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Tool;


namespace Core.Common
{
	class Tweeter
	{
		private WebClient webClient;
		public string Authorization { get => webClient.Headers["authorization"]; }
		public string Path { get; private set; }
		public string Token { get => webClient.Headers["x-guest-token"]; }

		public Tweeter(ref WebClient webClient, string authorization = "", string path = "", string token = "")
		{
			this.webClient = webClient;
			if (string.IsNullOrWhiteSpace(authorization) || string.IsNullOrWhiteSpace(path))
			{
				GetAuthorization();
			}
			else
			{
				webClient.Headers["authorization"] = authorization;
				Path = path;
			}
			if (string.IsNullOrWhiteSpace(token)) GetToken();
			else webClient.Headers["x-guest-token"] = token;
		}

		protected void GetAuthorization()
		{
			string @string = string.Empty;
			try
			{
				@string = Encoding.UTF8.GetString(webClient.DownloadData("https://twitter.com/"));
			}
			catch (WebException e)
			{
				LogHelp.WriteLine(e.ToString());
				if (e.Status == WebExceptionStatus.ProtocolError)
				{
					LogHelp.WriteLine("进入等待");
					Task.Delay(5 * 60 * 1000).Wait();
				}
				return;
			}
			Regex regex = new Regex("https(.*?)/main\\.(.*?)\\.js");
			string text = regex.Match(@string).Value;
			string string2 = Encoding.UTF8.GetString(webClient.DownloadData(text));
			Regex regex2 = new Regex("s=\"(A.*?)\"");
			string value = "Bearer " + regex2.Match(string2).Groups[1].Value;
			webClient.Headers["authorization"] = value;
			Path = new Regex("queryId:\"([a-zA-Z0-9-_]*?)\",operationName:\"UserByScreenName\"").Match(string2).Groups[1].Value;
		}

		protected void GetToken()
		{
			string value2 = string.Empty;
			//webClient.Headers["x-guest-token"] = value2;
			try
			{
				value2 = JObject.Parse(Encoding.UTF8.GetString(webClient.UploadData("https://api.twitter.com/1.1/guest/activate.json", new byte[0])))["guest_token"].ToString();
			}
			catch(WebException)
			{
				webClient.Dispose();
				webClient = new WebClient() { Proxy = webClient.Proxy };
				GetAuthorization();
			}
			webClient.Headers["x-guest-token"] = value2;
		}

		public string GetUserID(string userName)
		{
			string text2 = $"https://api.twitter.com/graphql/{Path}/UserByScreenName?variables=%7B%22screen_name%22%3A%22{userName}%22%2C%22withHighlightedLabel%22%3Afalse%7D";
			return JObject.Parse(Encoding.UTF8.GetString(webClient.DownloadData(text2)))["data"]["user"]["rest_id"].ToString();
		}

		public Tweet[] GetTweets(string userId)
		{
			string address = $"https://api.twitter.com/2/timeline/profile/{userId}.json?tweet_mode=extended&simple_quoted_tweet=true";
			string string3;
			try
			{
				string3 = Encoding.UTF8.GetString(webClient.DownloadData(address));
			}
			catch (WebException e)
			{
				LogHelp.WriteLine(e.ToString());
				if (int.TryParse(e.Response.Headers["status"], out int status))
				{
					LogHelp.WriteLine(e.ToString());
					LogHelp.WriteLine("状态码", status.ToString());
				}
				GetToken();
				return null;
			}
			var json = JObject.Parse(string3);
			List<Tweet> tweets = new List<Tweet>();
			foreach (var item in json["timeline"]["instructions"][0]["addEntries"]["entries"])
			{
				var entryId = item["entryId"].ToString();
				if (entryId.Contains("tweet"))
				{
					var id = item["sortIndex"].ToString();
					ParseTweet(json, id, out Tweet tweet);
					tweets.Add(tweet);
				}
			}
			return tweets.ToArray();
		}

		static void ParseTweet(JObject json, string tweetId, out Tweet tweet)
		{
			var temp = json["globalObjects"]["tweets"][tweetId] as JObject;
			if (temp != null)
			{
				tweet = new Tweet();
				tweet.ID = tweetId;
				tweet.CreatTime = DateTime.ParseExact(temp["created_at"].ToString(), "ddd MMM dd HH:mm:ss zzz yyyy", CultureInfo.InvariantCulture);
				var isRetweet = temp.ContainsKey("retweeted_status_id_str");
				var userId = temp["user_id_str"].ToString();
				tweet.UserName = json["globalObjects"]["users"][userId]["name"].ToString();
				if (temp.ContainsKey("extended_entities"))
				{
					var extended = temp["extended_entities"] as JObject;
					if (extended.ContainsKey("media"))
					{
						tweet.Media = extended["media"] as JArray;
					}
				}
				if (isRetweet)
				{
					var retweetId = temp["retweeted_status_id_str"].ToString();
					var full_text = temp["full_text"].ToString();
					if (!full_text.StartsWith("RT @"))
					{
						tweet.Content = full_text;
						tweet.IsOnlyRetweet = false;
					}
					else tweet.IsOnlyRetweet = true;
					ParseTweet(json, retweetId, out Tweet retweet);
					tweet.Retweet = retweet;
				}
				else
				{
					tweet.Content = temp["full_text"].ToString();
					tweet.Content = tweet.Content.Substring(0, temp["display_text_range"][1].ToObject<int>());
					if (temp.ContainsKey("quoted_status_id_str"))
					{
						ParseTweet(json, temp["quoted_status_id_str"].ToString(), out Tweet retweet);
						tweet.Retweet = retweet;
					}
				}
			}
			else tweet = null;
		}

		public class Tweet
		{
			public string ID { get; set; }
			public string Content { get; set; }
			public JArray Media { get; set; }
			public DateTime CreatTime { get; set; }
			public string UserName { get; set; }
			public Tweet Retweet { get; set; }
			public bool IsOnlyRetweet { get; set; }
		}
	}

	static public class TweetConfig
	{
		public static string Authorization;
		public static string Path;
		public static string Token;
	}
}
